package com.ideal.manage.esms.config.shiro;

import com.ideal.manage.esms.bean.sys.QUserProject;
import com.ideal.manage.esms.bean.sys.Role;
import com.ideal.manage.esms.bean.sys.User;
import com.ideal.manage.esms.bean.sys.UserProject;
import com.ideal.manage.esms.jpa.JpaRepositoryImpl;
import com.ideal.manage.esms.service.system.RoleMenuService;
import com.ideal.manage.esms.service.system.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.subject.WebSubject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Configuration
public class MyShiroRealm extends AuthorizingRealm {
    private static final Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);

    @Autowired
    private UserService userService;
    @Autowired
    private RoleMenuService roleMenuService;
    private JpaRepositoryImpl<UserProject, String> jpaRepository;
    @Autowired
    private EntityManager entityManager;

    @PostConstruct
    public void startup() {
        this.jpaRepository = new JpaRepositoryImpl<UserProject, String>(UserProject.class, entityManager);
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
        ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal();
        User user = userService.findById(shiroUser.getId());
        Role role = user.getRole();
        if (role.getName().equalsIgnoreCase("admin")) {
            shiroUser.setAdmin(true);
        }
        simpleAuthenticationInfo.addRole(role.getName());
        List<String> buttons = roleMenuService.getAllButton(role);
        if (buttons != null && !buttons.isEmpty()) {
            simpleAuthenticationInfo.addStringPermissions(buttons);
        }
        System.out.println("权限===");
        return simpleAuthenticationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("身份验证====");
        Date date = new Date();
        //获取用户输入的用户名密码
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        String username = usernamePasswordToken.getUsername();
        String password = String.valueOf(usernamePasswordToken.getPassword());
        //验证码
        HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils.getSubject()).getServletRequest();
        String captcha = request.getParameter("captcha");
        String exitCode = (String) SecurityUtils.getSubject().getSession().getAttribute("KAPTCHA_SESSION_KEY");
        if (captcha == null || !captcha.equalsIgnoreCase(exitCode)) {
            throw new AuthenticationException("验证码错误");
        }
        User user = userService.findByLoginNameAndPassword(username, password);
        if (user == null) {
            throw new IncorrectCredentialsException();
        }
        //保存用户的登陆时间
        user.setLastLoadTime(date);
        userService.save(user);

        ShiroUser shiroUser = new ShiroUser();
        shiroUser.setId(user.getId());
        shiroUser.setUsername(user.getLoginName());
        shiroUser.setPassword(user.getPassword());

        QUserProject qUserProject = QUserProject.userProject;
        List<String> projectIds = jpaRepository.query()
                .select(qUserProject.id)
                .from(qUserProject)
                .where(qUserProject.userId.id.eq(user.getId()))
                .fetch();
        shiroUser.setProjectIdSet(new HashSet<>(projectIds));

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(shiroUser, password, getName());
        return simpleAuthenticationInfo;
    }

    public static class ShiroUser implements Serializable {
        private String id;
        private String username;
        private String password;
        private boolean isAdmin;
        private Set<String> projectIdSet;

        public boolean isAdmin() {
            return isAdmin;
        }

        public void setAdmin(boolean admin) {
            isAdmin = admin;
        }

        public Set<String> getProjectIdSet() {
            return projectIdSet;
        }

        public void setProjectIdSet(Set<String> projectIdSet) {
            this.projectIdSet = projectIdSet;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }
}
